package com.shanghaionstar.remote.manager;

import android.content.Context;
import android.content.Intent;
import android.os.Message;
import android.support.v4.app.FragmentManager;

import com.onstar.cn.common.util.CommonUtil;
import com.onstar.cn.common.util.Constants;
import com.onstar.cn.framework.mvp.base.core.BaseActivity;
import com.onstar.cn.framework.utils.RxBus;
import com.onstar.cn.framework.utils.RxSubscriptions;
import com.onstar.cn.mag.enumtype.RemoteCommandsType;
import com.onstar.cn.map.common.PoiItemInfo;
import com.onstar.cn.rxconstants.RxConstants;
import com.onstar.cn.sqlite.entities.PollingEntity;
import com.onstar.cn.vehicle.entity.ErrorInfo;
import com.onstar.cn.vehicle.entity.RequestStatus;
import com.shanghaionstar.OnstarApplication;
import com.shanghaionstar.R;
import com.shanghaionstar.discover.model.WifiInfoModel;
import com.shanghaionstar.pin.model.PinModel;
import com.shanghaionstar.remote.model.RemoteModel;
import com.shanghaionstar.retrofit.http.RetrofitManager;
import com.shanghaionstar.utils.AlertDialogUtil;
import com.shanghaionstar.utils.ApplicationUtil;
import com.shanghaionstar.utils.BusinessUtil;

import java.lang.ref.SoftReference;

import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

import static com.onstar.cn.common.IServerUrls.serverURL;

/**
 * Created by onstarios on 2017/7/14.
 */

public class RemoteOperateManager {
    public boolean isRemoteCommanding;
    private Subscription subscription;
    private Subscription remotePageSubscription;
    public SoftReference<BaseActivity> ctxSr;
    private RxBus mBus;
    private RemoteModel model;

    private static class LazyHolder {
        private static final RemoteOperateManager INSTANCE = new RemoteOperateManager();
    }

    public static final RemoteOperateManager getInstance() {
        return LazyHolder.INSTANCE;
    }

    public RemoteOperateManager init(Context ctx) {
        if (isRemoteCommanding) {
            showDefaultCommanding(ctx);
        } else {
            mBus = RxBus.getDefault();
            this.ctxSr = new SoftReference(ctx);
            pinObserver();
        }
        return getInstance();
    }

    public void showDefaultCommanding(Context context) {
        if (context != null)
            AlertDialogUtil.showAlertDialog(context, context.getString(R.string.dialog_warning),
                    context.getString(R.string.service_inProcess_alert));
    }

    public void exeRemote(RemoteCommandsType type, Object... params) {
        if (!isRemoteCommanding) {
            isRemoteCommanding = true;
            model = new RemoteModel.Builder()
                    .setRemoteCommandsType(type)
                    .create();
            if (params != null && params.length > 0) {
                Object param = params[0];
                if (param instanceof WifiInfoModel) {
                    model.model = (WifiInfoModel) param;
                } else if (param instanceof PoiItemInfo) {
                    model.poiItemInfo = (PoiItemInfo) param;
                }
            }
            BaseActivity ctx = ctxSr.get();
            showPinOrNot(ctx.getSupportFragmentManager(), model);
        }
    }

    public void showPinOrNot(FragmentManager fragmentManager, RemoteModel remoteModel) {
        if (BusinessUtil.isAutoSendPin(remoteModel.getRemoteCommandsType(), ctxSr.get())) {
            commandByType(remoteModel);
            mBus.post(getPostMsg(RxConstants.REMOTE_WITHOUT_PING,remoteModel));
        } else {
            showPinDialogFragment(fragmentManager, remoteModel);
        }
    }

    private void showPinDialogFragment(FragmentManager fragmentManager, RemoteModel remoteModel) {
        PinDialogFragment pinDialogFragment = PinDialogFragment.newInstance(remoteModel.getRemoteCommandsType(), RxConstants.REMOTE_PING);
        pinDialogFragment.show(fragmentManager, "pin_dialog");
    }


    private void pinObserver() {
        remotePageSubscription = mBus.toObserverable(RxConstants.REMOTE_PING, Object.class)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object o) {
                        if (o != null && o instanceof PinModel) {
                            PinModel pinModel = ((PinModel) o);
                            handlePin(pinModel);
                        }
                    }
                });
        RxSubscriptions.add(remotePageSubscription);
    }

    private void handlePin(PinModel pinModel) {
        if (pinModel.isPinSuccess()) {
            if (model != null) {
                model.setFlash(pinModel.isFlash());
                model.setHorn(pinModel.isHorn());
            } else {
                model = new RemoteModel.Builder()
                        .setRemoteCommandsType(pinModel.getRemoteCommandsType())
                        .setFlash(pinModel.isFlash()).setHorn(pinModel.isHorn())
                        .create();
            }
            commandByType(model);
        }
    }



    public void commandByType(final RemoteModel remoteModel) {
        RemoteOperateHolder holder = new RemoteOperateHolder();
        String body = holder.getBody(remoteModel);
        String url = holder.getUrl(remoteModel.getRemoteCommandsType());

        subscription = RetrofitManager.getVehicleService()
                .commands(url, RetrofitManager.getHeaders(), body)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<PollingResponse>() {
                    @Override
                    public void call(PollingResponse res) {
                        PollingResponse.ErrorResponse error = res.getError();
                        if (!CommonUtil.isNull(error)) {
                            clear();
                            ErrorInfo errorInfo = new ErrorInfo();
                            errorInfo.setCode(error.getCode());
                            errorInfo.setDescription(error.getDescription());
                            mBus.post(getPostMsg(RxConstants.REMOTE_ERROR, errorInfo));
                            return;
                        }
                        PollingResponse.CommandResponse commandRes = res.getCommandResponse();
                        if (commandRes != null) {
                            String url = commandRes.getUrl();
                            String requestId = url.substring(url.lastIndexOf("s") + 2, url.length());
                            startPollVehicleStatus(remoteModel.getRemoteCommandsType(), requestId);
                            remoteModel.requestId = requestId;
                            mBus.post(getPostMsg(RxConstants.REMOTE_POLLING,remoteModel));
                        }
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        clear();
                        mBus.post(getPostMsg(RxConstants.REMOTE_ERROR,
                                BusinessUtil.getErrorInfoByException(OnstarApplication.getApplication(),
                                        new Exception(throwable.getMessage(), throwable))));
                    }
                });

    }


    public void startPollVehicleStatus(RemoteCommandsType commandsType, String requestId) {
        PollingEntity entity = new PollingEntity();
        entity.setVin(ApplicationUtil.getInstance().getCurrentVehicle().getVin());
        entity.setToken(ApplicationUtil.getInstance().getToken());
        entity.setRequestType(commandsType.value());
        entity.setRequestId(requestId);
        startPoll(entity);
    }


    public void startPoll(PollingEntity entity) {
        entity.setStartTime(System.currentTimeMillis() + "");
        entity.setRequestStatus(RequestStatus.InProgress.getStringValue());
        Intent intent = new Intent(ctxSr.get(), VehiclePollingService.class);
        intent.putExtra("pollingEntity", entity);
        intent.putExtra(Constants.SERVER_URL, serverURL);
        ctxSr.get().startService(intent);
    }

    public void clear() {
        isRemoteCommanding = false;
        if (subscription != null)
            subscription.unsubscribe();
        RxSubscriptions.clear();
        ctxSr = null;
    }

    public Message getPostMsg(int what,Object obj){
        Message message = Message.obtain();
        if(obj != null)
            message.obj = obj;
        message.what = what;
        return  message;
    }


}
